package com.yanqu.road.server.gameplayer.module.unioncampwar;

import com.yanqu.road.dao.impl.unioncampwar.UserUnionCampWarDaoImpl;
import com.yanqu.road.entity.enums.eLogMoneyType;
import com.yanqu.road.entity.enums.eMessageSubscribeType;
import com.yanqu.road.entity.enums.eSkillType;
import com.yanqu.road.entity.enums.eSystemId;
import com.yanqu.road.entity.kuang.KuangConfig;
import com.yanqu.road.entity.log.LogUnionCampWarAttack;
import com.yanqu.road.entity.messageSubscribe.entity.MessageUserNoticeData;
import com.yanqu.road.entity.player.UserBagItem;
import com.yanqu.road.entity.player.UserPatrons;
import com.yanqu.road.entity.unioncampwar.UserUnionCampWarData;
import com.yanqu.road.entity.unioncampwar.config.UnionCampWarBuffConfig;
import com.yanqu.road.logic.config.GameConfig;
import com.yanqu.road.logic.config.unioncampwar.UnionCampWarConfig;
import com.yanqu.road.pb.patrons.PatronsProto;
import com.yanqu.road.pb.unionCampWar.UnionCampWar;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.base.GeneralModule;
import com.yanqu.road.server.gameplayer.module.patrons.PatronsModule;
import com.yanqu.road.server.gameplayer.module.player.BagModule;
import com.yanqu.road.server.gameplayer.module.player.CurrencyModule;
import com.yanqu.road.server.gameplayer.module.player.PreReduceModule;
import com.yanqu.road.server.gameplayer.module.vehicle.VehicleModule;
import com.yanqu.road.server.logic.battle.BattleManager;
import com.yanqu.road.server.manger.ConfigMgr;
import com.yanqu.road.server.manger.activity.curio.CurioMgr;
import com.yanqu.road.server.manger.config.SystemOpenMgr;
import com.yanqu.road.server.manger.kuang.KuangMgr;
import com.yanqu.road.server.manger.log.AutoLogMgr;
import com.yanqu.road.server.manger.messagesubscribe.MessageSubscribeMgr;
import com.yanqu.road.server.protocol.ClientProtocol;
import com.yanqu.road.server.protocol.CrossProtocol;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.date.DateHelper;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.property.PropertyHelper;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class UnionCampWarModule extends GeneralModule {

    public UnionCampWarModule(GamePlayer player) {
        super(player);
    }

    private UserUnionCampWarData userData;


    private boolean isLoadDB = false;

    @Override
    public boolean loadData() {
        if (this.isLoadDB) {
            return true;
        }

        userData = new UserUnionCampWarDaoImpl().getUserUnionCampWarData(player.getUserId());

        this.isLoadDB = true;
        return true;
    }

    @Override
    public boolean afterLoadData() {
        return true;
    }

    @Override
    public void afterLogin() {
        if (!isSystemOpen()) {
            return;
        }
        this.initUserData();
        this.syncUserData();
    }

    public void initSystem() {
        if (!isSystemOpen()) {
            return;
        }
        this.initUserData();
        this.syncUserData();
    }

    /**
     * 设置推送时间
     */
    private void MessageSubscribePushTime(){
        if(!MessageSubscribeMgr.isSwitch()){
            return;
        }
        List<Long> timeList = new ArrayList<>();
        UnionCampWarConfig config = ConfigMgr.getUnionCampWarConfig();
        if (config == null) {
            return;
        }
        timeList.add(config.getNowWeekBattleTime() * DateHelper.SECOND_MILLIONS);
        MessageUserNoticeData noticeData = MessageSubscribeMgr.getUserNoticeData(player.getUserId());
        noticeData.setSubTime(eMessageSubscribeType.UnionCampWarTime, timeList);
    }

    @Override
    public boolean saveData() {
        if (userData != null) {
            if (userData.isInsertOption()) {
                new UserUnionCampWarDaoImpl().add(userData);
            } else if (userData.isUpdateOption()) {
                new UserUnionCampWarDaoImpl().update(userData);
            }
        }

        return true;
    }

    public boolean isSystemOpen() {

        return SystemOpenMgr.systemOpen(player, eSystemId.UnionCampWar.getValue());
    }

    private void initUserData() {
        if (!isSystemOpen()) {
            return;
        }
        if (null == userData) {
            userData = new UserUnionCampWarData(player.getUserId());
        }
        // 设置微信推送时间
        try {
            MessageSubscribePushTime();
        }catch (Exception e){
            log.error("error:" + e);
        }
    }

    public void syncUserData() {
        initUserData();
        if (null == userData) {
            return;
        }
        weekCheck();
        UnionCampWar.UnionCampWarUserDataSyncMsg.Builder syncMsg = UnionCampWar.UnionCampWarUserDataSyncMsg.newBuilder();
        syncMsg.setLastAttackTime(userData.getLastAttackTime());
        syncMsg.setAttackTimes(userData.getAttackTimes());
        syncMsg.setAttackTimesHave(getLeftAttackTimes());
        syncMsg.setLastAttackRecTime(userData.getRecoverTime());
        syncMsg.setCurioTimes(userData.getCurioTimes());
        syncMsg.setIsWorship(userData.isWorship());

        Map<Integer,List<Integer>> patronsAttackTimesMap = new HashMap<>();
        for (Map.Entry<Integer, Integer> entry : userData.getPatronsAttckTimesMap().entrySet()) {
            int patronsId = entry.getKey();
            int attckTimes = entry.getValue();
            List<Integer> list = patronsAttackTimesMap.get(patronsId);
            if (list == null) {
                list = new ArrayList<Integer>(){{
                    add(0);
                    add(0);
                }};
                patronsAttackTimesMap.put(patronsId, list);
            }
            list.set(0, attckTimes);
        }

        for (Map.Entry<Integer, Integer> entry : userData.getPatronsPayAttckTimesMap().entrySet()) {
            int patronsId = entry.getKey();
            int payTimes = entry.getValue();
            List<Integer> list = patronsAttackTimesMap.get(patronsId);
            if (list == null) {
                list = new ArrayList<Integer>(){{
                    add(0);
                    add(0);
                }};
                patronsAttackTimesMap.put(patronsId, list);
            }
            list.set(1, payTimes);
        }

        for (Map.Entry<Integer, List<Integer>> entry : patronsAttackTimesMap.entrySet()) {
            int patronsId = entry.getKey();
            List<Integer> list = entry.getValue();
            syncMsg.addPatronInfo(UnionCampWar.UnionCampWarPatronsTemp.newBuilder().setPatronsId(patronsId).setAttackTimes(list.get(0)).setCostTimes(list.get(1)));
        }

        player.sendPacket(Protocol.U_UNION_CAMP_WAR_USER_DATA_SYNC, syncMsg);
    }

    /**
     * 不是本周的数据重置
     */
    private void weekCheck() {
        int systemThisWeekId = GameConfig.getSystemThisWeekId();


        if (systemThisWeekId != userData.getWeekId()) {

            Property cost = new Property();
            //回收开宝库道具
            cost.addProperty(ConfigMgr.getUnionCampWarConfig().getLotteryCost());
            //回收进攻次数道具
            cost.addProperty(PropertyHelper.parseStringToProperty(GameConfig.SHANGBANG_ATTACK_NUM_COST));
            if (!cost.isNothing()) {
                for (Integer goodsId : cost.getGoods().keySet()) {
                    UserBagItem userBagItem = player.getModule(BagModule.class).getUserBagItem(goodsId);
                    if (userBagItem != null && userBagItem.getNum() > 0) {
                        player.getModule(CurrencyModule.class).removeCurrency(new Property(userBagItem.getGoodsId(), userBagItem.getNum()), eLogMoneyType.UnionCampWar, eLogMoneyType.UnionCampWarRecycle);
                    }
                }
            }


        }
        if (systemThisWeekId != userData.getWeekId()) {

            Calendar calendar = Calendar.getInstance();
            int day = calendar.get(Calendar.DAY_OF_WEEK);
            //六、日才重置玩家数据
            if(day != Calendar.SUNDAY && day != Calendar.SATURDAY){
                return;
            }

            userData.setWeekId(systemThisWeekId);
            userData.setLastAttackTime(0);
            userData.setAttackTimes(0);
            userData.setPatronsAttckTimesMap(new ConcurrentHashMap<>());
            userData.setPatronsPayAttckTimesMap(new ConcurrentHashMap<>());
            userData.setWorship(false);
            int times = getUserAttackTimes();
            userData.setLeftTimes(times);
            userData.setRecoverTime(ConfigMgr.getUnionCampWarConfig().getNowWeekBattleTime() * DateHelper.SECOND_MILLIONS);

        }
    }

    private int getUserAttackTimes() {
        int times = (int)CurioMgr.getSkillAdditionBySkillType(eSkillType.UnionCampWarSendTimesSkill.getValue(), player, 0);
        if(userData != null){
            userData.setCurioTimes(times);
        }
        return times + ConfigMgr.getUnionCampWarConfig().getAttackTimesMax();
    }

    /**
     * 进攻检查
     */
    public int checkAttackRet(List<Integer> patronsIds, int buffId, List<PatronsProto.PatronsSimpleTempMsg> patronsBattleInfoList, int attackType) {
        if (userData == null || patronsIds.isEmpty()) {
            return GameErrorCode.E_ERROR_DATA;
        }
        resetOneDay();

        if (!ConfigMgr.getUnionCampWarConfig().isInBattleTime()) {
            return GameErrorCode.E_UNION_CAMP_WAR_NOT_BATTLE_TIME;
        }

        if (patronsIds.size() > ConfigMgr.getUnionCampWarConfig().getAttackPatronsNum()) {
            return GameErrorCode.E_UNION_CAMP_WAR_LINEUP_PATRONS_NUM_MAX;
        }

        Property cost = new Property();
        List<UserPatrons> userPatronsList = new ArrayList<>();
        int ret = parseAttackParam(patronsIds, buffId, userPatronsList, cost, attackType);
        if (ret != 0) {
            return ret;
        }

        if (!cost.isNothing() && !player.getModule(CurrencyModule.class).currencyIsEnough(cost)) {
            return GameErrorCode.E_BAG_ITEM_NO_ENOUGH;
        }

        player.getModule(PreReduceModule.class).preReduce(cost);
        int addition = (int) CurioMgr.getSkillAdditionBySkillType(eSkillType.UnionCampWarPatronsEarnSkill.getValue(), player, 0);
        patronsBattleInfoList.addAll(BattleManager.getUnionCampWarAttackPatronsMsg(userPatronsList, addition));

        return 0;
    }

    public int parseAttackParam(List<Integer> patronsIds, int buffId, List<UserPatrons> userPatronsList, Property cost, int attackType) {
        UnionCampWarBuffConfig buffConfig = ConfigMgr.getUnionCampWarConfig().getBuffConfig(buffId);
        if (null == buffConfig) {
            return GameErrorCode.E_UNION_CAMP_WAR_ATTACK_BUFF_ERR;
        }

        cost.addProperty(buffConfig.getCost());//buff消耗

        if (attackType == 0) {
            if (getLeftAttackTimes() <= 0) {
                return GameErrorCode.E_UNION_CAMP_WAR_USER_NOT_ATTACK_TIMES;
            }
        } else {
            cost.addProperty(PropertyHelper.parseStringToProperty(GameConfig.SHANGBANG_ATTACK_NUM_COST));
        }

        //门客进攻次数消耗
        PatronsModule patronsModule = player.getModule(PatronsModule.class);
        for (Integer patronsId : patronsIds) {
            UserPatrons userPatrons = patronsModule.getUserPatrons(patronsId);
            if (null == userPatrons) {
                return GameErrorCode.E_PATRONS_NO_FOUND;
            }

            if (attackType == 0) {
                int patronsAttackTimes = userData.getPatronsAttckTimesMap().getOrDefault(patronsId, 0);
                if (patronsAttackTimes >= ConfigMgr.getUnionCampWarConfig().getPatronsAttackLimit()) {
                    return GameErrorCode.E_UNION_CAMP_WAR_PATRONS_NOT_ATTACK_TIMES;
                }
            } else {
                int payTimes = userData.getPatronsPayAttckTimesMap().getOrDefault(patronsId, 0);
                if (payTimes >= GameConfig.SHANGBANG_ATTACK_PARTON_NUM_LIMIT) {
                    return GameErrorCode.E_UNION_CAMP_WAR_PATRONS_NOT_ATTACK_TIMES;
                }
            }

            userPatronsList.add(userPatrons);
        }

        return 0;
    }

    public int getAttackTimes() {
        if (userData == null) {
            return 0;
        }
        return userData.getAttackTimes();
    }

    public int getLeftAttackTimes() {
        if (userData == null) {
            return 0;
        }
        if (ConfigMgr.getUnionCampWarConfig().isRecoverAttackTimes(userData.getLastAttackTime())) {
            userData.setLastAttackTime(DateHelper.getCurrentTime());
            userData.setLeftTimes(getUserAttackTimes());
        }

        return userData.getLeftTimes();
    }

    /**
     * 进攻结算
     */
    public void attackSettle(UnionCampWar.UnionCampWarAttackRespMsg respMsg) {
        UnionCampWar.UnionCampWarAttackResultTemp resultMsg = respMsg.getResult();

        Property cost = new Property();
        List<UserPatrons> userPatronsList = new ArrayList<>();
        int ret = parseAttackParam(resultMsg.getPatronsIdListList(), resultMsg.getBuffId(), userPatronsList, cost, respMsg.getAttackType());
        //返回预扣
        player.getModule(PreReduceModule.class).restorePreReduce(cost);

        if (respMsg.getRet() != 0) {
            player.sendPacket(ClientProtocol.U_UNION_CAMP_WAR_ATTACK_TEAM, respMsg.toBuilder());
            return;
        }

        player.getModule(CurrencyModule.class).removeCurrency(cost, eLogMoneyType.UnionCampWar, eLogMoneyType.UnionCampWarAttackCost);


        userData.setAttackTimes(userData.getAttackTimes() + 1);
        userData.setLastAttackTime(DateHelper.getCurrentTime());

        if (respMsg.getAttackType() == 0) {
            userData.setLeftTimes(userData.getLeftTimes() - 1);
        }

        String rewards = resultMsg.getRewards();
        player.getModule(CurrencyModule.class).addCurrency(rewards, eLogMoneyType.UnionCampWar, eLogMoneyType.UnionCampWarAttackReward);

        for (Integer patronsId : resultMsg.getPatronsIdListList()) {
            if (respMsg.getAttackType() == 0) {
                userData.incPatronsAttackTime(patronsId);
            } else {
                userData.incPatronsPayAttackTime(patronsId);
            }

            player.getModule(VehicleModule.class).bindPatronsSystem(patronsId, eSystemId.UnionCampWar.getValue(), DateHelper.getZeroTimeStamp(DateHelper.getCurrentTime() + DateHelper.DAY_MILLIONS) / 1000);
        }

        int thisWeekId = GameConfig.getSystemThisWeekId();

        player.sendPacket(ClientProtocol.U_UNION_CAMP_WAR_ATTACK_TEAM, respMsg.toBuilder());

        AutoLogMgr.add(new LogUnionCampWarAttack(thisWeekId, getUserId(),
                player.getUserInfo().getUnionUid(), resultMsg.getGroupId(),
                resultMsg.getOwnCampId(), resultMsg.getHoldId(), resultMsg.getEnemyCampId(),
                resultMsg.getBuffId(), resultMsg.getDefeatNum(), resultMsg.getRewards(), resultMsg.getSubHp(), resultMsg.getLeftHp(), respMsg.getAttackType()));

        syncUserData();
    }

    public void enterMainScence() {
        initUserData();
        if (userData == null) {
            return;
        }
        UnionCampWar.CrossUnionCampWarGetMainScenceReqMsg.Builder reqMsg = UnionCampWar.CrossUnionCampWarGetMainScenceReqMsg.newBuilder();
        reqMsg.setLastEnterTime(userData.getEnterTime());
        player.sendPacket(CrossProtocol.C3_UNION_CAMP_WAR_MAIN_SCENCE_INFO, reqMsg);
        userData.setEnterTime(DateHelper.getCurrentTime());
    }

    public int checkWorship() {
        if (userData == null) {
            return GameErrorCode.E_ERROR_DATA;
        }
        if (userData.isWorship()) {
            return GameErrorCode.E_UNION_CAMP_WAR_WORSHIPED;
        }
        return 0;
    }

    public void worshipBack() {
        userData.setWorship(true);
    }

    /**
     * 自然恢复进攻次数,优化又改了，废弃但不删
     */
    @Deprecated
    public void recoveryAttackTime() {
//        DateHelper.getCurrentTime();
//        if (userData != null) {
//            int logBeforeEnergy = userData.getLeftTimes();
//
//            CalcPowerResult result = PowerHelper.calcPower(
//                    userData.getRecoverTime() / DateHelper.SECOND_MILLIONS,
//                    ConfigMgr.getUnionCampWarConfig().getAttackTimesRecoverCD(),
//                    ConfigMgr.getUnionCampWarConfig().getAttackTimesRecoverValue(),
//                    ConfigMgr.getUnionCampWarConfig().getAttackTimesMax(),
//                    userData.getLeftTimes());
//            userData.setLeftTimes(result.getCurPower());
//            userData.setRecoverTime(result.getLastRecoverTime() * DateHelper.SECOND_MILLIONS);
//        }
    }

    public void resetOneDay() {
        if (userData == null) {
            return;
        }
        weekCheck();
        long currentTime = DateHelper.getCurrentTime();
        if (DateHelper.isSameDay(userData.getRecoverTime() / DateHelper.SECOND_MILLIONS, currentTime / DateHelper.SECOND_MILLIONS)) {
            return;
        }
        userData.setRecoverTime(currentTime);
        userData.setPatronsAttckTimesMap(new ConcurrentHashMap<>());
        userData.setPatronsPayAttckTimesMap(new ConcurrentHashMap<>());
    }
}
